package pl.kosmowska.ewelina.server.dao;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import pl.kosmowska.ewelina.server.jdo.OutcomeData;
import pl.kosmowska.ewelina.server.jdo.SavingsData;

import com.allen_sauer.gwt.log.client.Log;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class SavingsDataDAO extends JdoDAOImpl<SavingsData> {

	private static final Logger log = Logger.getLogger(SavingsDataDAO.class
			.getName());


	public SavingsData findSavingsData(String id) {
		Long uid = UserDataDAO.getLoggedInUserId();
		if (id == null) {
			return null;
		}
		
		List <OutcomeData> paidOutcomeList=null;
		paidOutcomeList=getPaidOutcomeList(id, new Date());

		
		Key key = KeyFactory.stringToKey(id);
		PersistenceManager pm = getPersistenceManager();
		try {
			SavingsData savingsData = pm.getObjectById(SavingsData.class, key);
//			if (SavingsData.getUserId() != uid) { // does the uid really own this Savings
//				SavingsData = null;
//			}
			updatePaymentStatus(paidOutcomeList, savingsData);
			return savingsData;
		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: SavingsData.findSavingsData(id): id=" + id, e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	private static void updatePaymentStatus(List<OutcomeData> paidOutcomeList, SavingsData savingsData) {
		if((paidOutcomeList==null)||(paidOutcomeList.isEmpty())){
			savingsData.setValuePaid(0);
			savingsData.setValueNotPaid(savingsData.getValue());
		}else{
			savingsData.setValuePaid(-countPaidSum(paidOutcomeList));
			savingsData.setValueNotPaid(savingsData.getValue()-savingsData.getValuePaid());
		}
		
	}

	private static float countPaidSum(List<OutcomeData> paidOutcomeList) {
		float sum=0;
		for(OutcomeData data:paidOutcomeList){
			sum+=data.getValue();
		}
		return sum;
	}


	public List<SavingsData> findSavingsDataByUser() {
		Long uid = UserDataDAO.getLoggedInUserId();

		// only pull up the owner's Savingss
		String qfilter = "userId==" + uid + "";
		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query = pm.newQuery("select from " + SavingsData.class.getName());
			query.setFilter(qfilter);
			List<SavingsData> list = (List<SavingsData>) query.execute();
			
			for(SavingsData SavingsData: list){
				List <OutcomeData> paidOutcomeList=null;
				paidOutcomeList=getPaidOutcomeList(SavingsData.getId(), new Date());
				updatePaymentStatus(paidOutcomeList, SavingsData);
			}

			List<SavingsData> r = (List<SavingsData>) pm.detachCopyAll(list);

			return r;
		} catch (Exception e) {
			Log.error("Error: SavingsData.findSavingsDataByUser(): qfilter=" + qfilter, e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	public SavingsData persist(SavingsData savingsData) {
		return (SavingsData) persistEntity(savingsData);
	}

	public SavingsData persist(SavingsData savingsData, List <OutcomeData> outcomeList) {

		Long uid = UserDataDAO.getLoggedInUserId();
		List <OutcomeData> previousOutcomeList=null;
		PersistenceManager pm = getPersistenceManager();
		if (savingsData.getVersion() !=null && savingsData.getVersion()!=0 ){
			previousOutcomeList=getCurrentOutcomeList(savingsData.getId(),pm);
			if((previousOutcomeList==null)||(previousOutcomeList.isEmpty())){
				log.severe("SavingsData.persist() Error: Something weird going on getting previous list. Empty list");
				return null;
			}

		}
		if (savingsData.getVersion()== null) {
			savingsData.setVersion(01l);
		}
		savingsData.setVersion(savingsData.getVersion()+1);
		Iterator<OutcomeData> newListItr = outcomeList.iterator();
		try {
			savingsData.setUserId(uid);
			pm.makePersistent(savingsData);
			
			while (newListItr.hasNext()) {
				OutcomeData tmp = newListItr.next();
				tmp.setUserId(uid);
				tmp.setVersion(01L);
				tmp.setGroupKey(savingsData.getId());
			}
			pm.makePersistentAll(outcomeList);
			if(previousOutcomeList!=null)
				pm.deletePersistentAll(previousOutcomeList);

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: SavingsData.persist(): this=" + this, e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return savingsData;
	}

	private List <OutcomeData> getCurrentOutcomeList(String id, PersistenceManager pm) {

		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.groupKey == groupId "
							+ " PARAMETERS String groupId ");
			List<OutcomeData> list = (List<OutcomeData>) query.execute(	id);

			if ((list == null) || (list.isEmpty())) {
				Log.error("SavingsData.getCurrentOutcomeList() Error: Empty list returned, wrong query?");
				return null;
			}

			return list;
		} catch (Exception e) {
			Log.error("Error: SavingsData.findOutcomeDataByUser():", e);
			e.printStackTrace();
		} 
		return null;

	}

	private void deleteCurrentOutcomeList(String id, PersistenceManager pm) {
		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.groupKey == groupId "
							+ " PARAMETERS String groupId ");
			 query.deletePersistentAll(id);

		} catch (Exception e) {
			log.log(Level.SEVERE,
					"Error: SavingsData.findOutcomeDataByUser()", e);
		}

	}
	private List <OutcomeData> getPaidOutcomeList(String id, Date date) {
		Date queryStartDate = getDate(date);
		PersistenceManager pm = getPersistenceManager();
		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.groupKey == groupId && this.date <= queryStartDate "
							+ " PARAMETERS String groupId, java.util.Date queryStartDate,");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(	id,queryStartDate );

			if ((list == null) || (list.isEmpty())) {
				Log.error("SavingsData.getPaidOutcomeList() Error: Empty list returned, wrong query?");
				return null;
			}

			return list;
		} catch (Exception e) {
			Log.error("Error: SavingsData.findOutcomeDataByUser()", e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;

	}

	private Date getDate(Date date) {
		java.util.Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(date.getYear() + 1900, date.getMonth(), date.getDate());
		return calendar.getTime();
	}

	public Boolean deleteSavingsData(String id) {

		if (id == null) {
			return false;
		}
		PersistenceManager pm = getPersistenceManager();
		deleteCurrentOutcomeList(id,pm);

		Long uid = UserDataDAO.getLoggedInUserId();
		Key key = KeyFactory.stringToKey(id);

		try {
			SavingsData e = pm.getObjectById(SavingsData.class, key);
			if (e.getUserId() != uid) { // check owner
				log.severe("SavingsData.remove() Error: Something weird going on in setting UID. e.getUserId()=" + e.getUserId() + " uid=" + uid);

			} else {
				pm.deletePersistent(e);
			}
			return true;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error:", e);
			e.printStackTrace();
		} finally {
			pm.close();
		}

		return false;
	}


}